package org.ourgrid.acceptance.broker;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.junit.Test;
import org.ourgrid.acceptance.util.broker.Req_302_Util;
import org.ourgrid.acceptance.util.broker.Req_304_Util;
import org.ourgrid.acceptance.util.broker.Req_309_Util;
import org.ourgrid.acceptance.util.broker.Req_311_Util;
import org.ourgrid.acceptance.util.broker.Req_312_Util;
import org.ourgrid.acceptance.util.broker.Req_327_Util;
import org.ourgrid.acceptance.util.broker.Req_328_Util;
import org.ourgrid.acceptance.util.broker.Req_329_Util;
import org.ourgrid.acceptance.util.broker.Req_330_Util;
import org.ourgrid.acceptance.util.broker.TestJob;
import org.ourgrid.broker.BrokerComponent;
import org.ourgrid.common.interfaces.LocalWorkerProvider;
import org.ourgrid.common.interfaces.to.GridProcessHandle;
import org.ourgrid.common.spec.peer.PeerSpec;
import org.ourgrid.common.spec.worker.WorkerSpec;
import org.ourgrid.reqtrace.ReqTest;

import br.edu.ufcg.lsd.commune.functionaltests.util.TestStub;
import br.edu.ufcg.lsd.commune.identification.DeploymentID;

@ReqTest(reqs="REQ330")
public class Req_330_Test extends BrokerAcceptanceTestCase {

	private Req_302_Util req_302_Util = new Req_302_Util(getComponentContext());
	private Req_304_Util req_304_Util = new Req_304_Util(getComponentContext());
	private Req_309_Util req_309_Util = new Req_309_Util(getComponentContext());
	private Req_311_Util req_311_Util = new Req_311_Util(getComponentContext());
	private Req_312_Util req_312_Util = new Req_312_Util(getComponentContext());
	private Req_327_Util req_327_Util = new Req_327_Util(getComponentContext());
	private Req_328_Util req_328_Util = new Req_328_Util(getComponentContext());
	private Req_329_Util req_329_Util = new Req_329_Util(getComponentContext());
	private Req_330_Util req_330_Util = new Req_330_Util(getComponentContext());
	
	/**
	* Create and start the Broker with the correct public key;
    * Call setPeers giving a list containing one peer with the following attributes:
          o First peer = username = test and servername = servertest
    * Call doNotifyRecovery passing a peer with username = test on the parameter;
    * Verify if the following debug message was logged:
          o Peer with object id: [X] is UP. Where X is the objectID generated.
    * Do login with the public key property set to "publicKey1" in the worker provider.
    * Add a job with the attributes: label: "Test Job" and one Task with remote 
    * 	attribute "echo Hello World"
    * Verify if the operation result contains a jobID with value 1.
    * Add a job with the attributes: label: "Test Job 2" and one Task with remote 
    * 	attribute "echo Hello World 2"
    * Verify if the operation result contains a jobID with value 2.
    * Call hereIsWorker giving a worker with public key "workerPublicKey1" and the 
    * 	request ID generated by job 1.
    * Call hereIsWorker giving a worker with public key "workerPublicKey2" and the 
    * 	request ID generated by job 2.
    * Call Worker doNotifyFailure giving the worker with public key = "workerPublicKey1";
    * Verify if the local worker provider with public key "publicKey1" has 
    * 	the disposeWorker message called;
    * Call Worker doNotifyFailure giving the worker with public key = "workerPublicKey1";
    * Verify if the following debug message was logged:
          o A peer notified a worker with public key [workerPublicKey1] failure, but it is not working to this broker.

	 * @throws Exception
	 */
	@ReqTest(test="AT-330.1", reqs="REQ330")
	@Test public void test_at_330_1_ScheduleTests() throws Exception {
		//start broker
		BrokerComponent broker = req_302_Util.startBroker();
		
		//set peer
		PeerSpec peer = req_309_Util.setPeers("username", "servertest", "publickey1", broker);
		
		//call doNotifyRecovery passing a peer with username test
		DeploymentID objID1 = req_328_Util.createPeerDeploymentID("publickey1", peer);
		TestStub testStub = req_327_Util.notifyPeerRecovery(peer, objID1, broker);
		
		//do login with peer
		req_311_Util.verifyLogin(broker, "publickey1", false, false, null, testStub);
		
		//add jobs
		List<LocalWorkerProvider> peers = new LinkedList<LocalWorkerProvider>();
		peers.add((LocalWorkerProvider) testStub.getObject());
		//add the first job
		TestJob testJob1 = req_304_Util.addJob(true, 1, broker, "echo Hello Word", "Test Job", peers);
		//add the second Job
		TestJob testJob2 = req_304_Util.addJob(true, 2, broker, "echo Hello Word 2", "Test Job 2", peers);
		
		Map<String, String> workerAttributes1 = new HashMap<String, String>();
		workerAttributes1.put(WorkerSpec.ATT_USERNAME, "worker1");
		workerAttributes1.put(WorkerSpec.ATT_SERVERNAME, "server1");
		
		Map<String, String> workerAttributes2 = new HashMap<String, String>();
		workerAttributes2.put(WorkerSpec.ATT_USERNAME, "worker2");
		workerAttributes2.put(WorkerSpec.ATT_SERVERNAME, "server2");
		
		//call here is worker with the request ID generated by job 1.
		TestStub testStub1 = req_312_Util.receiveWorker(broker, "workerPublicKey1", true, true, true, true, new WorkerSpec(workerAttributes1), "publickey1", testStub, testJob1);
		//call here is worker with the request ID generated by job 2.
		TestStub testStub2 = req_312_Util.receiveWorker(broker, "workerPublicKey2", true, true, true, true, new WorkerSpec(workerAttributes2), "publickey1", testStub, testJob2);
		
		//Worker doNotifyFailure call with public key = "workerPublicKey1"
		req_330_Util.notifyWorkerFailure("workerPublicKey1", new WorkerSpec(workerAttributes1), broker, 
				(LocalWorkerProvider) testStub.getObject(), false, testStub1.getDeploymentID());
		
		//Worker doNotifyFailure call with public key = "workerPublicKey1"
		req_330_Util.notifyWorkerFailure("workerPublicKey1", new WorkerSpec(workerAttributes1), broker, 
				(LocalWorkerProvider) testStub.getObject(), true, testStub1.getDeploymentID());
		
	}
	
	/**
	* Create and start the Broker with the correct public key;
    * Call setPeers giving a list containing one peer with the following attributes:
          o First peer = username = test and servername = servertest
    * Call doNotifyRecovery passing a peer with username = test on the parameter;
    * Verify if the following debug message was logged:
          o Peer with object id: [X] is UP. Where X is the objectID generated.
    * Do login with the public key property set to "publicKey1" in the worker provider.
    * Add a job with the attributes: label: "Test Job" and one Task with remote attribute 
    * 	"echo Hello World"
    * Verify if the operation result contains a jobID with value 1.
    * Add a job with the attributes: label: "Test Job 2" and one Task with remote attribute 
    * 	"echo Hello World 2"
    * Verify if the operation result contains a jobID with value 2.
    * Call hereIsWorker giving a worker with public key "workerPublicKey1" and the 
    * 	request ID generated by job 1.
    * Call hereIsWorker giving a worker with public key "workerPublicKey2" and the 
    * 	request ID generated by job 2.
    * Call Worker doNotifyFailure giving the worker with public key = "workerPublicKey1";
    * Verify if the local worker provider with public key "publicKey1" has the 
    * 	disposeWorker message called;
    * Call Worker doNotifyFailure giving the worker with public key = "workerPublicKey2";
    * Verify if the local worker provider with public key "publicKey1" has the 
    * 	disposeWorker message called;
    * Call Worker doNotifyFailure giving the worker with public key = "workerPublicKey1";
    * Verify if the following debug message was logged:
          o A peer notified a worker with public key [workerPublicKey1] 
          	failure, but it is not working to this broker.
    * Call Worker doNotifyFailure giving the worker with public key = "workerPublicKey2";
    * Verify if the following debug message was logged:
          o A peer notified a worker with public key [workerPublicKey2] 
          	failure, but it is not working to this broker.

	 * @throws Exception
	 */
	@ReqTest(test="AT-330.2", reqs="REQ330")
	@Test public void test_at_330_2_ScheduleTests() throws Exception {
		//start broker
		BrokerComponent broker = req_302_Util.startBroker();
		
		//set peer
		PeerSpec peer = req_309_Util.setPeers("username", "servertest", "publickey1", broker);
		
		//call doNotifyRecovery passing a peer with username test
		DeploymentID objID1 = req_328_Util.createPeerDeploymentID("publickey1", peer);
		TestStub testStub = req_327_Util.notifyPeerRecovery(peer, objID1, broker);
		
		//do login with peer
		req_311_Util.verifyLogin(broker, "publickey1", false, false, null, testStub);
		
		//add jobs
		List<LocalWorkerProvider> peers = new LinkedList<LocalWorkerProvider>();
		peers.add((LocalWorkerProvider) testStub.getObject());
		//add the first job
		TestJob testJob1 = req_304_Util.addJob(true, 1, broker, "echo Hello Word", "Test Job", peers);
		//add the second Job
		TestJob testJob2 = 	req_304_Util.addJob(true, 2, broker, "echo Hello Word 2", "Test Job 2", peers);
		
		Map<String, String> workerAttributes1 = new HashMap<String, String>();
		workerAttributes1.put(WorkerSpec.ATT_USERNAME, "worker1");
		workerAttributes1.put(WorkerSpec.ATT_SERVERNAME, "server1");
		
		Map<String, String> workerAttributes2 = new HashMap<String, String>();
		workerAttributes2.put(WorkerSpec.ATT_USERNAME, "worker2");
		workerAttributes2.put(WorkerSpec.ATT_SERVERNAME, "server2");
		
		//call here is worker with the request ID generated by job 1.
		TestStub testStub1 = req_312_Util.receiveWorker(broker, "workerPublicKey1", true, true, true, true, new WorkerSpec(workerAttributes1), 
				"publickey1", testStub, testJob1);
		//call here is worker with the request ID generated by job 2.
		TestStub testStub2 = req_312_Util.receiveWorker(broker, "workerPublicKey2", true, true, true, true, new WorkerSpec(workerAttributes2), 
				"publickey1", testStub, testJob2);
		
		//Worker doNotifyFailure call with public key = "workerPublicKey1"
		req_330_Util.notifyWorkerFailure("workerPublicKey1", new WorkerSpec(workerAttributes1), broker, 
				(LocalWorkerProvider) testStub.getObject(), false, testStub1.getDeploymentID());
		
		//Worker doNotifyFailure call with public key = "workerPublicKey2"
		req_330_Util.notifyWorkerFailure("workerPublicKey2", new WorkerSpec(workerAttributes2), broker, 
				(LocalWorkerProvider) testStub.getObject(), false, testStub2.getDeploymentID());
		
		//Worker doNotifyFailure call with public key = "workerPublicKey1"
		req_330_Util.notifyWorkerFailure("workerPublicKey1", new WorkerSpec(workerAttributes1), broker, 
				(LocalWorkerProvider) testStub.getObject(), true, testStub1.getDeploymentID());
		
		//Worker doNotifyFailure call with public key = "workerPublicKey2"
		req_330_Util.notifyWorkerFailure("workerPublicKey2", new WorkerSpec(workerAttributes2), broker, 
				(LocalWorkerProvider) testStub.getObject(), true, testStub2.getDeploymentID());
	}
	
	/**
	*Create and start the Broker with the correct public key;
    * Call setPeers giving a list containing one peer with the following attributes:
          o First peer = username = test and servername = servertest
    * Call doNotifyRecovery passing a peer with username = test on the parameter;
    * Verify if the following debug message was logged:
          o Peer with object id: [X] is UP. Where X is the objectID generated.
    * Do login with the public key property set to "publicKey1"in the worker provider.
    * Add a job with the attributes: label: "Test Job" and one Task with remote attribute 
    * 	"echo Hello World"
    * Verify if the operation result contains a jobID with value 1.
    * Add a job with the attributes: label: "Test Job 2" and one Task with remote attribute
    * 	 "echo Hello World 2"
    * Verify if the operation result contains a jobID with value 2.
    * Call hereIsWorker giving a worker with public key "workerPublicKey1" and the request 
    * 	ID generated by job 1.
    * Call hereIsWorker giving a worker with public key "workerPublicKey2" and the request 
    * 	ID generated by job 2.
    * Call schedule with the correct public key;
    * Verify if the worker's startWork message was called;
    * Call Worker doNotifyFailure giving the worker with public key = "workerPublicKey1";
    * Verify if the local worker provider with public key "publicKey1" has the disposeWorker
    * 	message called;
    * Call Worker doNotifyFailure giving the worker with public key = "workerPublicKey1";
    * Verify if the following debug message was logged:
          o A peer notified a worker with public key [workerPublicKey1] failure, but it is 
          	not working to this broker.
    * Call Worker doNotifyFailure giving the worker with public key = "workerPublicKey2";
    * Verify if the local worker provider with public key "publicKey1" has the disposeWorker 
    * 	message called;
    * Call Worker doNotifyFailure giving the worker with public key = "workerPublicKey2";
    * Verify if the following debug message was logged:
          o A peer notified a worker with public key [workerPublicKey2] failure, but it is 
          	not working to this broker.
    * Call hereIsWorker giving a worker with public key "workerPublicKey3" and the request 
    * 	ID generated by job 1.

	 * @throws Exception
	 */
	@ReqTest(test="AT-330.3", reqs="REQ330")
	@Test public void test_at_330_3_ScheduleTests() throws Exception {
		//start broker
		BrokerComponent broker = req_302_Util.startBroker();
		
		//set peer
		PeerSpec peer = req_309_Util.setPeers("username", "servertest", "publickey1", broker);
		
		//call doNotifyRecovery passing a peer with username test
		DeploymentID objID1 = req_328_Util.createPeerDeploymentID("publickey1", peer);
		TestStub testStub = req_327_Util.notifyPeerRecovery(peer, objID1, broker);
		
		//do login with peer
		req_311_Util.verifyLogin(broker, "publickey1", false, false, null, testStub);
		
		//add jobs
		List<LocalWorkerProvider> peers = new LinkedList<LocalWorkerProvider>();
		peers.add((LocalWorkerProvider) testStub.getObject());
		//add the first job
		TestJob testJob1 = req_304_Util.addJob(true, 1, broker, "echo Hello Word", "Test Job", peers);
		//add the second Job
		TestJob testJob2 = req_304_Util.addJob(true, 2, broker, "echo Hello Word 2", "Test Job 2", peers);
		
		Map<String, String> workerAttributes1 = new HashMap<String, String>();
		workerAttributes1.put(WorkerSpec.ATT_USERNAME, "worker1");
		workerAttributes1.put(WorkerSpec.ATT_SERVERNAME, "server1");
		
		Map<String, String> workerAttributes2 = new HashMap<String, String>();
		workerAttributes2.put(WorkerSpec.ATT_USERNAME, "worker2");
		workerAttributes2.put(WorkerSpec.ATT_SERVERNAME, "server2");
		
		//call here is worker with public key "workerPublicKey1" and the request ID generated by job 1.
		TestStub testStub1 = req_312_Util.receiveWorker(broker, "workerPublicKey1", true, true, true, true, new WorkerSpec(workerAttributes1), 
				"publickey1", testStub, testJob1);
		//call here is worker with public key "workerPublicKey2" and the request ID generated by job 2.
		TestStub testStub2 = req_312_Util.receiveWorker(broker, "workerPublicKey2", true, true, true, true, new WorkerSpec(workerAttributes2), 
				"publickey1", testStub, testJob2);
		
		//call schedule with the correct public key
		List<TestStub> testStubs = new LinkedList<TestStub>();
		testStubs.add(testStub1);
		testStubs.add(testStub2);
		
		List<TestJob> jobs = new ArrayList<TestJob>();
		jobs.add(testJob1);
		jobs.add(testJob2);
		
		List<GridProcessHandle> handles = new ArrayList<GridProcessHandle>();
		handles.add(new GridProcessHandle(1, 1, 1));
		handles.add(new GridProcessHandle(2, 1, 1));
		
		List<TestStub> peerStubs = new ArrayList<TestStub>();
		peerStubs.add(testStub);
		
		req_329_Util.doSchedule(broker, testStubs, peerStubs, jobs, handles); 
		
		//Worker doNotifyFailure call with public key = "workerPublicKey1"
		req_330_Util.notifyWorkerFailure("workerPublicKey1", new WorkerSpec(workerAttributes1), broker, (LocalWorkerProvider) testStub.getObject(), false,
				testStub1.getDeploymentID(), true, new GridProcessHandle(1, 1, 1));
		
		//Worker doNotifyFailure call with public key = "workerPublicKey1"
		req_330_Util.notifyWorkerFailure("workerPublicKey1", new WorkerSpec(workerAttributes1), broker, (LocalWorkerProvider) testStub.getObject(), true,
				testStub1.getDeploymentID());
		
		//Worker doNotifyFailure call with public key = "workerPublicKey2"
		req_330_Util.notifyWorkerFailure("workerPublicKey2", new WorkerSpec(workerAttributes2), broker, (LocalWorkerProvider) testStub.getObject(), false,
				testStub2.getDeploymentID(), true, new GridProcessHandle(2, 1, 1));
		
		//Worker doNotifyFailure call with public key = "workerPublicKey2"
		req_330_Util.notifyWorkerFailure("workerPublicKey2", new WorkerSpec(workerAttributes2), broker, (LocalWorkerProvider) testStub.getObject(), true,
				testStub2.getDeploymentID());
		
		//call here is worker with public key "workerPublicKey3" and the request ID generated by job 1.
		Map<String, String> workerAttributes3 = new HashMap<String, String>();
		workerAttributes3.put(WorkerSpec.ATT_USERNAME, "worker3");
		workerAttributes3.put(WorkerSpec.ATT_SERVERNAME, "server3");
		
		req_312_Util.receiveWorker(broker, "workerPublicKey3", true, true, true, true, new WorkerSpec(workerAttributes3), "publickey1", testStub, testJob1);
	}
}
